import json
import re
import string

from fastapi import APIRouter, Request
from re_common.baselibrary.tools.all_requests.aiohttp_request import AioHttpRequest
from re_common.baselibrary.tools.all_requests.mrequest import MRequest
from re_common.baselibrary.utils.core.mlamada import bools_string
from re_common.baselibrary.utils.core.requests_core import MsgCode


from apps.allsubdb.proxies_control.models import PostProxy
from apps.core.m_route import ContextIncludedRoute
from apps.core.return_info import ReturnInfo, FAILED, SUCCESS
from apps.crawler_platform.core_api.models import UpdateTaskModel
from apps.crawler_platform.core_platform.core_g import SQLTable, CoreSqlValue
from apps.crawler_platform.core_platform.core_sql import CoreSqlMixin
from apps.crawler_platform.core_platform.g_model import InputPlatformModel, journalInputMode, journalIssueMode, \
    journalArticleMode, journalHomeMode
from apps.crawler_platform.qk_platform.journal_article_down import JournalArtilceDownStep
from apps.crawler_platform.qk_platform.journal_home import JournalHomeDownStep
from apps.crawler_platform.qk_platform.journal_issue_down import JournalIssueDownStep
from apps.crawler_platform.qk_platform.journal_qk_down import JournalDownStep
from settings import get_settings

router = APIRouter(route_class=ContextIncludedRoute)


@router.post("/journal/downhome")
async def downhomejournal(request: Request, input: InputPlatformModel[journalHomeMode]):
    """
    下载期刊首页
    :return:
    """

    return_info = ReturnInfo()
    down = JournalHomeDownStep(request, input)
    bools, err_info = await down.my_task()
    step_info = down.step_info
    return_info.status = bools_string(bools)
    if bools:
        return_info.msg_code = 200
        return_info.msg = step_info
        return_info.data = ""
    else:
        return_info.msg_code = 400
        return_info.msg = step_info
        return_info.data = {"err_info": err_info}

    return return_info.todict()


@router.post("/journal/downjournal")
async def downjournal(request: Request, input: InputPlatformModel[journalInputMode]):
    """
    下载期刊列表
    :return:
    """
    return_info = ReturnInfo()
    down = JournalDownStep(request, input)
    bools, err_info = await down.my_task()
    step_info = down.step_info
    return_info.status = bools_string(bools)
    if bools:
        return_info.msg_code = 200
        return_info.msg = step_info
        return_info.data = ""
    else:
        return_info.msg_code = 400
        return_info.msg = step_info
        return_info.data = {"err_info": err_info}

    return return_info.todict()


@router.post("/journal/downissue")
async def downjournal(request: Request, input: InputPlatformModel[journalIssueMode]):
    """
    下载期刊列表
    :return:
    """
    return_info = ReturnInfo()
    down = JournalIssueDownStep(request, input)
    bools, err_info = await down.my_task()
    step_info = down.step_info
    return_info.status = bools_string(bools)
    if bools:
        return_info.msg_code = 200
        return_info.msg = step_info
        return_info.data = ""
    else:
        return_info.msg_code = 400
        return_info.msg = step_info
        return_info.data = {"err_info": err_info}

    return return_info.todict()


@router.post("/journal/downarticle")
async def downjournal(request: Request, input: InputPlatformModel[journalArticleMode]):
    """
    下载期刊列表
    :return:
    """
    return_info = ReturnInfo()
    down = JournalArtilceDownStep(request, input)
    bools, err_info = await down.my_task()
    step_info = down.step_info
    return_info.status = bools_string(bools)
    if bools:
        return_info.msg_code = 200
        return_info.msg = step_info
        return_info.data = ""
    else:
        return_info.msg_code = 400
        return_info.msg = step_info
        return_info.data = {"err_info": err_info}
    return return_info.todict()


async def get_proxy(task_name, task_tag):
    """
    获取代理接口
    """
    data = InputPlatformModel(
        data=PostProxy(task_name=task_name,
                       task_tag=task_tag
                       )).json()
    url = get_settings().PROXY_URL
    rrq = AioHttpRequest()
    rrq.set_url(url) \
        .set_timeout(30) \
        .set_data(data) \
        .set_middler_list(
        [rrq.is_null_html_middlerwares, rrq.status_code_middlerwares])
    bools, dicts = await rrq.run(MRequest.POST)
    if bools:
        proxy = json.loads(rrq.html)["data"]
        return bools, proxy
    else:
        return bools, 'nothing'


async def chaoxing_post_cookie(cookie):
    basekey = {"task_name": "chaoxingjournal", "task_tag": "chaoxingjournallist", "order_num": 1, "groups": "1"}
    upset = [{"key": "headers", "value": {"key": "Cookie", "value": cookie}, "type": "dict", "flag": "False"}]
    data = InputPlatformModel(
        data=UpdateTaskModel(basekey=basekey,
                             upset=upset
                             )).json()
    url = get_settings().UPDATE_TASK
    rrq = AioHttpRequest()
    rrq.set_url(url) \
        .set_timeout(30) \
        .set_data(data) \
        .set_middler_list(
        [rrq.is_null_html_middlerwares, rrq.status_code_middlerwares])
    bools, dicts = await rrq.run(MRequest.POST)
    if bools:
        return bools
    else:
        return bools


@router.post("/chaoxingjournal/get_cookie")
async def get_cookie(input: InputPlatformModel[journalInputMode]):
    """
        获取超星cookie 接收期刊ID参数 进行对应请求,以防止对单个URL请求过多导致被封风险
    """
    return_info = ReturnInfo()
    pa_list = list()
    rule1 = re.compile("'Set-Cookie': \'(.*?)\'")
    rule2 = re.compile(";.*")
    bools, proxies = await get_proxy("chaoxing_cookie", "cx_cookie")
    journal_rawid = input.data.journal_rawid
    if bools:
        headers = {
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
            "Host": "qikan.chaoxing.com",
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36'

        }
        url = "http://qikan.chaoxing.com/mag/infos?mags=%s" % (journal_rawid)
        rrq = AioHttpRequest()
        rrq.set_url(url).set_sn(None) \
            .set_timeout(30).set_allow_resp_text(False).set_allow_redirects(False) \
            .set_proxy(proxies).set_header(headers).set_middler_list([])
        boolsg, dicts = await rrq.run(MRequest.GET)
        if boolsg:
            cookie1_str = rrq.resp.headers
            cookie1_str_list = re.findall(rule1, str(cookie1_str))
            for i in cookie1_str_list:
                pa = rule2.sub("", i)
                pa_list.append(pa)
            cookie1 = ";".join(pa_list)
            pa_list.clear()
            headers["Host"] = "fxlogin.chaoxing.com"
            headers["Cookie"] = "cookiecheck=true"
            if "Location" in str(cookie1_str):
                url = cookie1_str['Location']
            else:
                url = ""
            rrq.set_url(url).set_sn(None) \
                .set_timeout(30).set_allow_redirects(False) \
                .set_proxy(proxies).set_header(headers).set_middler_list([])
            boolsg2, dicts2 = await rrq.run(MRequest.GET)
            if boolsg2:
                cookie2_str = rrq.resp.headers
                cookie2_str_list = re.findall(rule1, str(cookie2_str))
                for i in cookie2_str_list:
                    if not i.startswith("JSESSIONID"):
                        pa = rule2.sub("", i)
                        pa_list.append(pa)
                cookie2 = ";".join(pa_list)
                cookie = ";".join([cookie1, cookie2])
                bools_post = await chaoxing_post_cookie(cookie)
                if bools_post:
                    return_info.status = SUCCESS
                    return_info.msg_code = 200
                    return_info.msg = "cookie请求成功"
                    return_info.data = {"Cookie": cookie}
                    return return_info.todict()
                else:
                    return_info.status = FAILED
                    return_info.msg_code = MsgCode.CHAOXIN_COOKIE_ERROR
                    return_info.msg = "请求存储API失败"
                    return_info.data = ""
                    return return_info.todict()
            else:
                return_info.status = FAILED
                return_info.msg_code = MsgCode.CHAOXIN_COOKIE_ERROR
                return_info.msg = "代理请求二级目标网页失败"
                return_info.data = ""
                return return_info.todict()

        else:
            return_info.status = FAILED
            return_info.msg_code = MsgCode.CHAOXIN_COOKIE_ERROR
            return_info.msg = "代理请求一级目标网页失败"
            return_info.data = ""
            return return_info.todict()


@router.post("/wanfanghome/init")
async def init_wf_home():
    return_info = ReturnInfo()
    lists = []
    dicts = {
        "home_rawid": "0/",
        "task_name": "wanfangjournal",
        "task_tag": "wanfangclasshome",
        "sub_db_id": "00004",
        "home_json": "{}",
    }
    lists.append(dicts)
    for i in string.digits + string.ascii_uppercase:
        t = dicts.copy()
        t["home_rawid"] = i
        t["task_tag"] = "wanfangqkhome"
        lists.append(t)
    list_v = []
    list_key = list(lists[0].keys())
    for item in lists:
        list_v.append(tuple(item.values()))
    bools, dicts = await CoreSqlMixin.insert_many_sql(SQLTable.journal_home, list_key, list_v,
                                                      insert=CoreSqlValue.insert_ig_it)
    if not bools:
        return_info.status = FAILED
        return_info.msg_code = MsgCode.SQL_INSERT_ERROR
        return_info.msg = "insert_many_sql 出现错误"
    else:
        return_info.status = SUCCESS
        return_info.msg_code = 200
        return_info.msg = "insert_many_sql 初始化成功"
    return return_info.todict()


@router.post("/cnkihome/init")
async def init_cnki_home():
    return_info = ReturnInfo()
    lists = []
    dicts = {
        "home_rawid": "1",
        "task_name": "cnkijournal",
        "task_tag": "cnkiclasshome",
        "sub_db_id": "00002",
        "home_json": "{}",
    }
    lists.append(dicts)

    list_v = []
    list_key = list(lists[0].keys())
    for item in lists:
        list_v.append(tuple(item.values()))
    bools, dicts = await CoreSqlMixin.insert_many_sql(SQLTable.journal_home, list_key, list_v,
                                                      insert=CoreSqlValue.insert_ig_it)
    if not bools:
        return_info.status = FAILED
        return_info.msg_code = MsgCode.SQL_INSERT_ERROR
        return_info.msg = "insert_many_sql 出现错误"
    else:
        return_info.status = SUCCESS
        return_info.msg_code = 200
        return_info.msg = "insert_many_sql 初始化成功"
    return return_info.todict()


@router.post("/chaoxinghome/init")
async def init_wf_home():
    return_info = ReturnInfo()
    lists = []
    dicts = {
        "home_rawid": "1",
        "task_name": "chaoxingjournal",
        "task_tag": "chaoxinghome",
        "sub_db_id": "00006",
        "home_json": "{}",
    }
    dicts1 = {
        "home_rawid": "",
        "task_name": "chaoxingjournal",
        "task_tag": "chaoxingqkhomeclass",
        "sub_db_id": "00006",
        "home_json": "{}",
    }
    lists.append(dicts)
    lists.append(dicts1)
    list_v = []
    list_key = list(lists[0].keys())
    for item in lists:
        list_v.append(tuple(item.values()))
    bools, dicts = await CoreSqlMixin.insert_many_sql(SQLTable.journal_home, list_key, list_v,
                                                      insert=CoreSqlValue.insert_ig_it)
    if not bools:
        return_info.status = FAILED
        return_info.msg_code = MsgCode.SQL_INSERT_ERROR
        return_info.msg = "insert_many_sql 出现错误"
    else:
        return_info.status = SUCCESS
        return_info.msg_code = 200
        return_info.msg = "insert_many_sql 初始化成功"
    return return_info.todict()
